#include "mqtt_chat.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"

//============================临时测试用=============================
esp_mqtt_client_handle_t emcht = NULL;
mqtt_chat_obj* mqtt_chat_test;
//MQTT事件处理函数
static void mqtt_event_fun(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
    if(event_id==MQTT_EVENT_CONNECTED){                 //连接上MQTT服务器
        mqtt_chat_test = mqtt_chat_new("esp32/test_name");
        printf("success connect mqtt\r\n");
    }else if(event_id==MQTT_EVENT_DISCONNECTED){        //断开MQTT服务器连接
        printf("lose connect mqtt\r\n");
    }else if(event_id==MQTT_EVENT_DATA){                //收到订阅信息
        esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t )event_data;   //强转获取存放订阅信息的参数
        printf("receive data : %.*s from %.*s\r\n",event->data_len,event->data,event->topic_len,event->topic);
        mqtt_chat_rec_message(mqtt_chat_test, event->data);
    }
}

void mqtt_init(void)
{
    const esp_mqtt_client_config_t mqtt5_cfg = {
        .broker.address.uri="mqtt://xiangchen.work",  //MQTT服务器的uri
        .session.protocol_ver = MQTT_PROTOCOL_V_5,
        .network.disable_auto_reconnect = true,
        .credentials.username = "ischen",
        .credentials.authentication.password = "ischen3364",
    };
    emcht = esp_mqtt_client_init(&mqtt5_cfg);           //初始化MQTT客户端获取句柄
    if(!emcht)  printf("mqtt init error!\r\n");
    
    //注册MQTT事件处理函数
    if (esp_mqtt_client_register_event(emcht,ESP_EVENT_ANY_ID,mqtt_event_fun,NULL)!=ESP_OK) {
        printf("mqtt register error!\r\n");
    } else {
        printf("mqtt register OK!\r\n");
    }
 
    //开启MQTT客户端
    if (esp_mqtt_client_start(emcht) != ESP_OK) {
         printf("mqtt start error!\r\n");
    } else {
         printf("mqtt start OK!\r\n");
    }
    mqtt_chat_init(&emcht);
}

//==================================================================

static esp_mqtt_client_handle_t mqttclient = NULL;

esp_err_t mqtt_chat_init(esp_mqtt_client_handle_t *_mqttclient)
{
    mqttclient = *_mqttclient;
    return ESP_OK;
}

mqtt_chat_obj* mqtt_chat_new(const char *name)
{
    mqtt_chat_obj *chat = (mqtt_chat_obj *)malloc(sizeof(mqtt_chat_obj));
    chat->mes_point = 0;
    chat->mes_num = 0;
    chat->who = strdup(name);
    if (esp_mqtt_client_subscribe(mqttclient, chat->who, 0) < 0) {
        printf("mqtt_chat_new err!\r\n");
        goto err;
    }
    return chat;
err:
    free(chat->who);
    free(chat);
    chat = NULL;
    return chat;
}

void mqtt_chat_del(mqtt_chat_obj *chat)
{
    esp_mqtt_client_unsubscribe(mqttclient, chat->who);
    if (chat->mes_num) {
        while (chat->mes_num) {
            free(chat->message[chat->mes_point]->mes);
            free(chat->message[chat->mes_point]->time);
            free(chat->message[chat->mes_point]);
            if (chat->mes_point == 0) {
                chat->mes_point = MQTT_CHAT_MESSAGE_MAX;
            }
            chat->mes_point--;
            chat->mes_num--;
        }
        free(chat->message);
    }
    free(chat->who);
    free(chat);
    chat = NULL;
}

esp_err_t mqtt_chat_rec_message(mqtt_chat_obj *chat, char *data)
{
    chat->message[chat->mes_point] = malloc(sizeof(mqtt_chat_message));
    chat->message[chat->mes_point]->mes = strdup(data);
    chat->message[chat->mes_point]->dir = mqtt_message_rec;
    //TODO chat->message[chat->mes_point]->time
    chat->mes_point++;
    chat->mes_num++;
    return ESP_OK;
}

esp_err_t mqtt_chat_send_message(mqtt_chat_obj *chat, char *data)
{
    chat->message[chat->mes_point] = malloc(sizeof(mqtt_chat_message));
    chat->message[chat->mes_point]->mes = strdup(data);
    chat->message[chat->mes_point]->dir = mqtt_message_send;
    //TODO chat->message[chat->mes_point]->time
    chat->mes_point++;
    chat->mes_num++;
    esp_mqtt_client_publish(emcht, chat->who, data, strlen(data), 0, 0);
    return ESP_OK;
}
